package trading.algo.BullTask;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import trading.algo.STKShortSellingTask;
import trading.algo.TimerKillerTask;
import trading.bo.DBAccessorBO;
import trading.bo.EmailAccessorBO;
import trading.bo.IBAccessorBO;
import trading.dataentry.MonitoredStocks;
import trading.dataentry.StockPositionOrOrder;
import trading.util.OrderSplitHelper;

/**
 * Note that protection order is created at the same time with the short order
 * 
 * @author ntantai
 * 
 */
public class NewSTKShortOrdersTask extends TimerTask {

    private IBAccessorBO ibAccessorBO;
    private DBAccessorBO dbAccessorBO;
    private EmailAccessorBO emailAccessorBO;
    private OrderSplitHelper orderSplitHelper;
    private double trailAmount;
    private double stopPrice;

    public NewSTKShortOrdersTask(IBAccessorBO ibAccessorBO,
            DBAccessorBO dbAccessorBO, EmailAccessorBO emailAccessorBO,
            double trailAmount, double stopPrice, OrderSplitHelper orderSplitHelper) {
        this.ibAccessorBO = ibAccessorBO;
        this.dbAccessorBO = dbAccessorBO;
        this.emailAccessorBO = emailAccessorBO;
        this.trailAmount = trailAmount;
        this.orderSplitHelper = orderSplitHelper;
        this.stopPrice = stopPrice;
    }

    @Override
    public void run() {
        // Step 1: check available fund and net liquidation.
        double netLiquidation = this.dbAccessorBO.getNetLiquidation();
        double availableFund = netLiquidation - getOccupiedFund();
        double availablePercent = 100 * availableFund / netLiquidation;
        // Step 2: determine percentage of fund to be added to the order.
        double investPercent = 0;
        if (availablePercent > 10 || availableFund > 1500) {
            investPercent = availablePercent;
        } else {
            // Do not proceed if we don't have much to invest.
            return;
        }

        // Step 3: get latest tick price.
        MonitoredStocks UVXYStat = this.dbAccessorBO
                .getMonitoredStockData(MonitoredStocks.TICKERS.UVXY.name());

        // Step 4: calculate order size
        int orderSize = (int) (netLiquidation * investPercent / (100.0 * UVXYStat
                .getLastPrice()));
        
        boolean shouldSplitOrder = true;
        if (orderSize < 300) {
            shouldSplitOrder = false;
        }

        // Step 5: place order
        Timer timer = new Timer();
        int taskID = 0;
        STKShortSellingTask stkShortSellingTask = new STKShortSellingTask(
                MonitoredStocks.TICKERS.UVXY.name(), orderSize, ibAccessorBO,
                emailAccessorBO, orderSplitHelper, shouldSplitOrder);
        timer.schedule(stkShortSellingTask, taskID * 1000);
        taskID += 20;

        // Step 6: place protection order
        STKShortProtectionOrderTask stkShortProtectionOrderTask = new STKShortProtectionOrderTask(
                MonitoredStocks.TICKERS.UVXY.name(), orderSize, ibAccessorBO,
                emailAccessorBO, this.trailAmount, this.stopPrice);
        timer.schedule(stkShortProtectionOrderTask, taskID * 1000);
        taskID += 2;

        // Step 7: Kill timer
        TimerKillerTask timerKillerTask = new TimerKillerTask(timer);
        timer.schedule(timerKillerTask, taskID * 1000);

    }
    
    private double getOccupiedFund() {
        double occupiedFund = 0;
        List<StockPositionOrOrder> stockPositions = this.dbAccessorBO.getPortfolioStockPositions();
        for (StockPositionOrOrder stockPosition : stockPositions) {
            double lastPrice = this.dbAccessorBO.getMonitoredStockData(stockPosition.getTicker()).getLastPrice();
            occupiedFund += Math.abs(Integer.parseInt(stockPosition.getQuantity())) * lastPrice;
        }
        return occupiedFund;
    }
}
